TMPLTER
=======

Генерация текстовых документов из файлов CSV на основе шаблонов (шаблонизатор).

Исполняемые модули: <https://gitverse.ru/panarinv/index/content/master/programs/tmplter>.  
Исходный код: <https://gitverse.ru/panarinv/tmplter>.


ВОЗМОЖНОСТИ
-----------

Программа формирует тексты на основе переданных файлов данных
 и шаблона, содержащего правила размещения данных в тексте.
Шаблон определяет общий вид текста и содержит метки вывода массивов данных.
Польза программы - отделение данных от их представления.

Особенности работы:

* шаблон может работать с несколькими массивами данных;
* поддерживается вложенность массивов данных
  (строки данных объединяются по одинаковым значениям одноимённых полей);
* программа получает шаблон из стандартного потока ввода,
  каталог с файлами данных указывается в параметрах.

Программа НЕ предназначена:

* для фильтрации данных или объединения массивов данных по сложной логике
  (в шаблон попадают все данные из файлов);
* для выполнения каких-либо расчётов или форматирования выводимых данных
  (программа просто записывает значения из файлов данных по указанным меткам).


ТРЕБОВАНИЯ
----------

Установка не требуется, достаточно скопировать исполняемый файл для нужной ОС.
От пользователей требуется знания и навыки работы с файлами формата CSV
 и правил обработки шаблонов (см. далее).


ИСПОЛЬЗОВАНИЕ
-------------

Программа использует текстовый (консольный) интерфейс.
Для запуска введите команду:

    tmplter [параметры] csv-файл(ы)... <шаблон >результат
    
    Параметры:
      -d <символ> - разделитель полей в файлах данных (по умолчанию TAB).

Результаты выводятся в стандартный поток вывода данных.


ПРИМЕР
------

Файлы данных:

    book.txt:
      book
      Книга 1

    dics.txt:
      DicName  DicCaption
      Dic1     Словарь 1
      Dic2     Словарь 2
      Dic3     Словарь 3

    dicitems.txt:
      DicName  ItemName  ItemCaption
      Dic1     Item1     Элемент 1
      Dic1     Item2     Элемент 2
      Dic1     Item3     Элемент 3
      Dic2     Item4     Элемент 4
      Dic3     Item5     Элемент 5
      Dic3     Item6     Элемент 6

Шаблон вывода данных:

    Заголовок {{book.txt/}}{{book}}{{/book.txt}}{{dics.txt/}}
    Словарь: "{{DicCaption}}"{{dicitems.txt/}}
      Элемент: "{{ItemCaption}}";{{/dicitems.txt}}{{/dics.txt}}
    Все элементы:{{dicitems.txt/}}
      {{ItemCaption}}{{/dicitems.txt}}
    Подвал

Получаемый текст:

    Заголовок Книга 1
    Словарь: "Словарь 1"
      Элемент: "Элемент 1";
      Элемент: "Элемент 2";
      Элемент: "Элемент 3";
    Словарь: "Словарь 2"
      Элемент: "Элемент 4";
    Словарь: "Словарь 3"
      Элемент: "Элемент 5";
      Элемент: "Элемент 6";
    Все элементы:
      Элемент 1
      Элемент 2
      Элемент 3
      Элемент 4
      Элемент 5
      Элемент 6
    Подвал


### Пояснения к примеру

Текст в начале шаблона выводится без изменений - "`Заголовок·`"
 (включая завершающий пробел).

Далее, обнаружив метку "`{{book.txt/}}{{book}}{{/book.txt}}`",
 программа находит массив (файл) данных "`book.txt`"
 с одни полем "`book`" и одной строкой данных "`Книга 1`".
В результате метка просто заменяется на значение "`Книга 1`".
Если бы в файле "`book.txt`" было бы несколько записей,
 то все значения записались бы в текст шаблона друг за другом без разделителей.

Далее программа обнаруживает открывающую метку массива "`{{dics.txt/}}`".
Это шаблон для вывода записей из "`dics.txt`".
Текст внутри метки "`{{dics.txt/}}...{{/dics.txt}}`"
 (содержимое метки) выглядит так:

    <перевод-строки>
    Словарь: "{{DicCaption}}"{{dicitems.txt/}}
      Элемент: "{{ItemCaption}}";{{/dicitems.txt}}

Файл "`dics.txt`" содержит три записи и вышеуказанный фрагмент шаблона
 будет записан в результирующий текст три раза (для каждой записи).
Перед выводом текст внутри метки анализируется так же как и исходный шаблон:

- Фрагмент "`<перевод-строки>Словарь:·"`" выводится без изменений
 для каждой строки в файле "`dics.txt`".
 Из-за наличия в начале содержимого перевода строки каждый фрагмент
  для записи из массива "`dics.txt`" будет выводится с новой строки.
- Метка "`{{DicCaption}}`" заменяется на значение из поля "DicCaption"
  (для каждой строки своё).
- Двойная кавычка выводится "как есть".
- Далее идёт открывающая метка массива "`{{dicitems.txt/}}`"
  и описываемые процессы повторяются для массива данных "`dicitems.txt`"
  за одним важным исключением...

Поскольку перебор элементов массива "`dicitems`"
 выполняется внутри другого перебора - массива "`dics`",
 программа предполагает, что элементы массивов связаны.
Связь элементов устанавливается по одинаковым значениям одноимённых полей.
В данном случае таким полем является "`DicName`".
Т.е. при выводе во внешнем массиве строки "`Dic1     Словарь 1`"
 во вложенном массиве программа оставит только строки,
 где одноименное поле "`DicName`" имеет значение "`Dic1`".
И, соответственно, после строки "`Словарь: "Словарь 1"`"
 выведет три записи "`<перевод-строки>  Элемент: "{{ItemCaption}}";`",
 последовательно заменив "`{{ItemCaption}}`"
 значениями "`Элемент 1`", "`Элемент 2`" и "`Элемент 3`".

Текст, оставшийся после последней метки в шаблоне,
 выводится в итоговый документ без изменений - "`<перевод-строки>Подвал`".


ОПИСАНИЕ
--------

### Правила работы с массивами данных

Массив данных - файл формата CSV содержащий строки данных для подстановки в шаблон.
Первая строка массива данных должна содержать заголовки полей
 по которым программа находит нужное поле (значение) для подстановки в шаблон.

Если по условиям шаблона один массив данных вложен в другой,
 то программа объединяет массивы данных по одинаковым значениям одноимённых полей
 (массивы "`dics.txt`" и "`dicitems.txt`" в примере выше).
Т.е. на каждой итерации внешнего массива во вложенном массиве выводятся только
 строки в которых совпадают значения одноимённых полей.

### Правила обработки шаблонов

Шаблон - текст (файл) содержащий метки вывода массивов данных и значений.

Программа ищет в шаблоне метки вида "`{{имя-файла/}}содержимое{{/имя-файла}}`".
Программе должен быть передан массив данных "`имя-файла`"
 строки из которого и будут подставляться в текст шаблона вместо найденной метки.

Текст `содержимое` копируется для каждой строки из массива данных "`имя-файла`".
В тексте "`содержимое`" программа вновь ищет метки вывода других массивов данных
 или метки вывода значений - "`{{имя-поля}}`".

При обнаружении метки вывода значений ("`{{имя-поля}}`") она будет заменена
 на значения из указанного поля текущий строки массива.

Если в `содержимом` обнаруживается метка вывода другого массива данных,
 то этот массив выводится как вложенный.
Если во вложенном и внешнем массивах есть поля с одинаковыми именами,
 то программа берёт из вложенного массива только те строки,
 значения по одноимённым полям в которых совпадают со внешним массивом
 (или все строки - если одноимённых полей не нашлось).

### Сжатие файлов CSV

Получаемые файлы данных могут быть сжаты по технологии GZIP.

### Расход оперативной памяти

В процессе работы все данные из всех переданных файлов CSV
 содержатся в оперативной памяти, что может замедлить обработку больших файлов
 на компьютерах с недостаточным количеством свободной оперативной памяти.


ЛИЦЕНЗИЯ
--------

Это свободное программное обеспечение.
Вы можете повторно распространять или изменять его
 в соответствии с условиями лицензии BSD.
Полный текст лицензии в файле LICENSE.

`(c) 2018-2024 Вячеслав Панарин (panarinv@mail.ru)`
